package com.coolingme.calculate;

import com.coolingme.calculate.expression.NumberExpression;
import com.coolingme.calculate.expression.TerminalExpression;

import java.util.Stack;

/**
 * 计算器，简单实现，没有做运算符优先级，默认使用空格隔开每个元素
 *
 * @author wangyue
 * @date 2020-09-29 23:03
 */
public class Calculator {

    /**
     * 表达式的栈
     */
    private Stack<IMathExpression> stack = new Stack<>();

    public Calculator(String expression) {
        this.parse(expression);
    }

    /**
     * 解析表达式
     *
     * @param expression 表达式
     */
    private void parse(String expression) {
        // 默认就用空格分割
        String[] elements = expression.split(" ");

        IMathExpression left, right;

        for (int i = 0; i < elements.length; i++) {
            // 当前元素
            String element = elements[i];
            if (OperatorUtil.isOperator(element)) {
                // 当前元素是操作符
                // 左边的数字表达式从栈中获取
                left = this.stack.pop();
                // 右边的数字为++i个元素，正好下一个循环从 (++i)++ 开始
                right = new NumberExpression(Integer.valueOf(elements[++i]));
                // 根据操作符和数字表达式获取 计算后的表达式
                TerminalExpression terminalExpression = OperatorUtil.getExpression(left, element, right);
                // 将计算后的表达式放入栈中
                this.stack.push(terminalExpression);
                System.out.println("出栈：" + left.interpret() + " " + element + " " + right.interpret());
            } else {
                // 当前元素是数字，转为数字表达式
                NumberExpression numberExpression = new NumberExpression(Integer.valueOf(element));
                // 将数字放入栈中
                this.stack.push(numberExpression);
                System.out.println("入栈：" + numberExpression.interpret());
            }
        }

    }

    /**
     * 计算表达式的值
     *
     * @return 计算结果
     */
    public int caculate() {
        // 栈中最后一个（也应该是唯一一个）表达式的值
        TerminalExpression terminalExpression = (TerminalExpression) this.stack.pop();
        return terminalExpression.interpret();
    }

}
